package shop.up.product.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import shop.up.product.service.TestService;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class TestServiceImpl implements TestService {

   @Autowired
   private StringRedisTemplate redisTemplate;

   @Override
   public void testLock() {
      String uuid = UUID.randomUUID().toString();
      // 1. 从redis中获取锁, setnx
      // 加锁
      Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 3, TimeUnit.SECONDS);
      if (lock) {
         // 查询redis中的num值
         String value = (String)this.redisTemplate.opsForValue().get("num");
         // 没有该值return
         if (StringUtils.isBlank(value)){
            return ;
         }
         // 有值就转成成int
         int num = Integer.parseInt(value);
         // 把redis中的num值+1
         redisTemplate.opsForValue().set("num", String.valueOf(++num));

         // 包装删除锁的原子性
         //  定义一个 lua 脚本
         String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

         //  准备执行lua 脚本
         DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
         //  将lua脚本放入DefaultRedisScript 对象中
         redisScript.setScriptText(script);
         //  设置DefaultRedisScript 这个对象的泛型
         redisScript.setResultType(Long.class);
         //  执行删除
         redisTemplate.execute(redisScript, Arrays.asList("lock"), uuid);
      } else {
         // 3. 每隔100毫秒回调一次，再次尝试获取锁
         try {
            Thread.sleep(100);
            testLock();
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}
